/*
 * Main.c
 *
 */ 

#include <avr/io.h>

#include <avr/eeprom.h>
#include <stdio.h>
#include <math.h>
#include <avr/interrupt.h>


#include "UART.h"
#include "SPI.h"
#include "I2C.h"

#include "Clock.h"
#include "LCD.h"

#include "Termometer.h"
#include "WindVane.h"
#include "Anemometer.h"

// LCD Variables
uint8_t lcd_refresh_time=1;
int32_t lcd_last=-4;
uint8_t lcd_index=0;

// Measure Variables
uint16_t temperature;	// 9 bits (+125 to -55)
uint8_t windSpeed;		// 7 bits (0 to 128)
uint16_t windDirection; // 9 bits (0 to 359)
date_t measure1_date;	// Date of the first memory
uint8_t isFirstMeasure=1; // First Measure

//Memory block 
typedef  uint32_t mem_block_t;

// Functions declarations
void print();
void take_samples();
void send_data();
void init_drivers();


//////////////////////////////////////////////////////////////////////////
//																		//
//								Main									//
//																		//
//////////////////////////////////////////////////////////////////////////
int main(void)
{
	// Sample timing
	uint8_t sample_time=60; // Minutes between samples
	int32_t last_sample=-sample_time; // Last sample time
	
	// Memory
	mem_block_t *mem_next=0; // Memory address for the next block 
	mem_block_t block; // Memory block for storing measures 
	
	
	
	// Initialize Drivers 
	init_drivers();
	

	//
	//	Main Loop
	//
	while(1)
	{
		//
		//	Take samples 
		//
		if(seconds - last_sample >= sample_time)
		{
			
			last_sample=seconds; // Upate time mark
			
			// Take samples from sensors
			take_samples();
			
			//
			// Write into memory
			//
			block=0; // Reset block
			block+= (uint32_t)(temperature) << 16; // Bits 16~23
			block+=(uint32_t)(windDirection) << 7; // Bits 7~15
			block+=windSpeed; // Bits 0~6
			
			eeprom_busy_wait(); // Wait for eeprom
			eeprom_write_block(&block,mem_next,sizeof(block)); // Write block

			mem_next++; // Update next address pointer
		}
		
		//			
		// Show Results in the LCD
		//
		print();
		
		//
		// UART
		//
		if(UART_ReadyRead()) // If there is a byte available
		{
			char byte=UART_ReadByte();
			
			//
			//	Send Data
			//
			if(byte==20)
			{
				// Auxiliary memory pointer
				mem_block_t *pBlock=0;
				// Read all blocks in memory
				// and send it throw UART
				while(pBlock!=mem_next)
				{
					eeprom_busy_wait();
					eeprom_read_block(&block,pBlock,sizeof(block));
					UART_WriteBlock(&block,sizeof(block));
					pBlock++;
				}
				
				// End of transmission
				block=0x70000000;
				UART_WriteBlock(&block,sizeof(block));	
				
				// Clear memory
				mem_next=0;
				isFirstMeasure=0;	
			}
			
			//
			//	Config
			//
			else if(byte==40)
			{
				
				date_t date;
				
				// Read the date
				date.year=UART_ReadByte();
				date.month=UART_ReadByte();
				date.day=UART_ReadByte();
				date.hour=UART_ReadByte();
				date.minutes=UART_ReadByte();
				date.seconds=UART_ReadByte();
				
				// Set system date
				Clock_SetDate(date);
				
				// Read sample time (in minutes)
				sample_time=UART_ReadByte()*60;
				
				// Clear memory
				mem_next=0;
				isFirstMeasure=0;
				
				
				
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////
//																		//
//							Init Drivers								//
//																		//
//////////////////////////////////////////////////////////////////////////
void init_drivers()
{
	//
	// Init drivers
	//
	cli();
	
	UART_Init(9600,8);
	SPI_Init();
	I2C_init();
	
	Clock_Init();
	Clock_SetDate(Clock_CreateDate(12,1,1,0,0,0));
	
	Vane_Init();
	ANEMO_Init();
	LCD_Init();
	


	sei();
}

//////////////////////////////////////////////////////////////////////////
//																		//
//								Print									//
//																		//
//////////////////////////////////////////////////////////////////////////

void print()
{

	if( seconds - lcd_last >= lcd_refresh_time)
	{
		lcd_last=seconds;
				
		switch(lcd_index)	
		{
			//
			// Temperature	
			//
			case 0:
			{
				// Integer part
				int8_t intpart=(int8_t)(temperature >> 1);
					
				char aux[30];
				// Float part: .5 ??
				if( (temperature & 0x01) ) // If temperature[0]==1
					sprintf(aux,"Temp: % 2d.%1d",intpart,5);
				else
					sprintf(aux,"Temp: % 2d",intpart);
					
				LCD_Clear();
				LCD_WriteString(aux);
			}
			break;
			
			//
			// Direction
			//
			case 1:
			{
				char aux[30];
				sprintf(aux,"Wind Dir: %3d",windDirection);
				LCD_Clear();
				LCD_WriteString(aux);
			}			
			break;
			
			//
			// Wind Speed
			//
			case 2:		
			{
				char aux[30];
				double inpart;
				
				// Float and integer part of wind speed in km/h (2 decimal precision)
				uint8_t floatpart= modf(ANEMO_FreqToMS(windSpeed),&inpart)*100;
						
				LCD_Clear();
				LCD_WriteString("Wind Speed");
						
				LCD_GotoXY(0,1);
				
				if(floatpart)
					sprintf(aux,"%d.%d Km/h",(int)inpart,floatpart);
				else
					sprintf(aux,"%d Km/h",(int)inpart);
					
				LCD_Clear();
				LCD_WriteString(aux);
						
			}
			break;		
				
			//
			//	Date
			//
			case 3:
				{
					date_t d=Clock_Date();
					char aux[30];
					sprintf(aux,"% 2d/%02d/%02d",d.year,d.month,d.day);
					LCD_Clear();
					LCD_WriteString(aux);
						
					sprintf(aux,"%02d:%02d:%02d",d.hour,d.minutes,d.seconds);
					LCD_GotoXY(0,1);
					LCD_WriteString(aux);
						
				}	
			break;						
		}	// Switch
				
				
		lcd_index++;
		lcd_index=lcd_index % 4;
	}

}

//////////////////////////////////////////////////////////////////////////
//																		//
//								sample									//
//																		//
//////////////////////////////////////////////////////////////////////////

void take_samples()
{
	// Read from sensors
	temperature=Temp_Read();
	windDirection = Vane_Read();
	windSpeed = ANEMO_Read();

	// First measure??
	if(isFirstMeasure)
	{
		measure1_date=Clock_Date();
		isFirstMeasure=0;
	}		
}			
